from typing import Dict

from PyQt6.QtCore import Qt, pyqtSignal, QRectF
from PyQt6.QtGui import QPainter, QCursor, QAction
from PyQt6.QtWidgets import QWidget, QMenu

from gui.route import Route
from gui.utils import FLAG_ALIGN_CENTER, get_resource_icon
from gui.utils.colors import EnvironmentColor, DIM_GREY
from gui.utils.size import WORLD_SIZE, RESOURCE_HEIGHT
from state.block import WorldBlock
from state.game_state import GameState
from state.player import Player
from utils.event_bus import EventBus


class PanelWorld(QWidget):
    update_resource_panel = pyqtSignal()

    def __init__(self, state: GameState, parent=None):
        super(PanelWorld, self).__init__(parent)

        self.state: GameState = state
        self.w = WORLD_SIZE / state.word_size
        self.setGeometry(0, RESOURCE_HEIGHT, WORLD_SIZE, WORLD_SIZE)
        self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.player: Player = self.state.players[self.state.obverse]

        EventBus.register('update_panel_world', self.update)
        EventBus.register('update_resource_display', self.update_filter_mode)

        self.display_mode = {
            'resource_details': False
        }

        self.route_map: Dict[str, Route | None] = {
            'explore': Route(None, [(0, 0), (0, 1), (1, 1), (1, 2)])
        }

    def paintEvent(self, event):
        painter = QPainter(self)

        match self.state.filter:
            case 0:
                self.__paint_filter_0(painter)
            case 1:
                self.__paint_filter_1(painter)

        for route in self.route_map.values():
            if route is not None:
                route.draw(painter, self.w)

    # 探索模式
    def __paint_filter_0(self, painter: QPainter):
        h = self.w / 3
        for pos in self.state.world_block_map.keys():
            block: WorldBlock = self.state.world_block_map[pos]
            sx, sy = pos[1] * self.w, pos[0] * self.w
            rect = QRectF(sx, sy, self.w, self.w)

            if pos not in self.player.discover_blocks:
                painter.setBrush(DIM_GREY)
                painter.drawRect(rect)
                # painter.drawText(rect, FLAG_ALIGN_CENTER, f'{pos}')
                continue

            painter.setBrush(EnvironmentColor[block.env + 2])
            painter.drawRect(rect)

            if self.display_mode['resource_details']:
                for index, (res_name, res_produce) in enumerate(block.produce.items()):
                    r = QRectF(sx, sy + h * index, h, h)
                    painter.setBrush(Qt.GlobalColor.white)
                    painter.drawRect(r)
                    painter.drawPixmap(r.toRect(), get_resource_icon(res_name))
                    r1 = QRectF(r.x() + h, r.y(), h, h)
                    painter.setPen(Qt.GlobalColor.black)
                    painter.drawText(r1, FLAG_ALIGN_CENTER, str(res_produce))

            if block.player == self.player.name:
                painter.setBrush(self.player.color)
                painter.drawEllipse(QRectF(sx + h * 2, sy, h, h))

            # painter.drawText(rect, FLAG_ALIGN_CENTER, f'{pos}')

    # 领土模式
    def __paint_filter_1(self, painter: QPainter):
        for pos in self.state.world_block_map.keys():
            block: WorldBlock = self.state.world_block_map[pos]
            if block.player == self.player.name:
                painter.setBrush(self.player.color)
            else:
                painter.setBrush(DIM_GREY)

            painter.drawRect(QRectF(pos[1] * self.w, pos[0] * self.w, self.w, self.w))

    def mouseReleaseEvent(self, event):
        pos = event.pos()
        row, col = int(pos.y() / self.w), int(pos.x() / self.w)

        if event.button() == Qt.MouseButton.LeftButton:
            b: WorldBlock = self.state.world_block_map[(row, col)]

            # 可见性检查
            if b.player == self.player.name or (row, col) in self.player.discover_blocks:
                info = b.info()
                pos = f'{row},{col}'
            else:
                info = ''
                pos = ''

            EventBus.publish('update_info', info)
            EventBus.publish('update_zoning_block', pos)
        else:
            self.create_menu(row, col)

    # 右键菜单
    def create_menu(self, r, c):
        b: WorldBlock = self.state.world_block_map[(r, c)]
        actions = list()

        if self.player.check_visible(b):
            if not self.player.check_belong_me(b):
                def __occupy_block():
                    self.player.add_block(b)
                    EventBus.publish('update_panel_resource')
                    self.update()

                action = QAction('占领', self)
                action.triggered.connect(__occupy_block)
                actions.append(action)
        else:
            b_neighbor = False
            for block in b.neighbors(self.state.world_block_map):
                if block.pos in self.player.discover_blocks:
                    b_neighbor = True
                    break

            if b_neighbor:
                def __obverse_block():
                    self.player.discover_block(b)
                    self.update()

                action = QAction('发现', self)
                action.triggered.connect(__obverse_block)
                actions.append(action)
            else:
                EventBus.publish('update_info', '不在已探索区域周围')

        if len(actions) > 0:
            menu = QMenu(self)
            for action in actions:
                menu.addAction(action)
            menu.popup(QCursor.pos())

    def update_filter_mode(self, name):
        self.display_mode[name] = not self.display_mode[name]
        self.update()
